<?php defined('SYSPATH') or die('No direct script access.');

class Controller_Admin_Merchmanagement_Items extends Controller_Admin_Template {

	const INDEX_PAGE = 'admin/merchmanagement/items/';
	
	public function before() {
		parent::before();
		
		$this->template->title = __('Merchandise Management');
	}
	
	public function action_index() {
		$category_id = $this->request->param('id');
		$category = ORM::factory('category', $category_id);
		$items = $category->items->where('discontinued', '=', 0)->order_by('name', 'asc')->find_all();	
		$view = View::factory('admin/merchmanagement/items/index');
		$view->set('category', $category);
		$view->set('items', $items);
		$this->template->content = $view;
	}
	
	public function action_delete() {
		$item_id = $this->request->param('id');
		$item = ORM::factory('item', $item_id);
		$item->discontinued = 1;
		$item->save();
		$this->request->redirect('admin/merchmanagement/items/index/'.$item->category->id);
	}
	
	public function action_add() {
		$category_id = $this->request->param('id');
		$category = ORM::factory('category', $category_id);
		
		$attributes = $category->attributes->find_all();
		
		$item = new Model_Item();
		$item->category_id = $category_id;
		
		$view = View::factory('admin/merchmanagement/items/add');
		$view->set('item', $item);
		$view->set('category', $category);
		$view->set('attributes', $attributes);
		
		$this->template->content = $view;
	}
	
	public function action_create() {
		$category_id = $this->request->param('id');
		$category = ORM::factory('category', $category_id);	
		$attributes = $category->attributes->order_by('name', 'asc')->find_all();
		
		$view = View::factory('admin/merchmanagement/items/create');
		$view->set('category', $category);
		$view->set('attributes', $attributes);
		$view->set('values', $_POST);
		$view->bind('errors', $errors);
		
		if($_POST) {
			$item = ORM::factory('item')
				->values($_POST);
			
			$external_values = array(
				'image' => Arr::get($_FILES, 'image'),
			);
			
			$extra = Validation::factory($external_values)
				->rule('image', 'Upload::not_empty', array(':value'))
				->rule('image', 'Upload::image', array(':value'))
				->rule('image', 'Upload::valid');
			
				try {
					$item->save($extra);
					$image_id = $this->_save_image($_FILES['image']);
					$item->image_id = $image_id;
					$item->save();
					
					// save attributes
					$attributes = $item->category->attributes->find_all();
					foreach($attributes as $attr):
						if(isset($_POST['attr'.$attr->id])) {
							$item_attribute = ORM::factory('itemAttribute');
							$item_attribute->item_id = $item->id;
							$item_attribute->attribute_id = $attr->id;
							$item_attribute->save();
							foreach($attr->values->find_all() as $val) :
								if(isset($_POST['value'.$val->id])) {
									$item_attribute_value = ORM::factory('itemAttributeValue');
									$item_attribute_value->itemattribute_id = $item_attribute->id;
									$item_attribute_value->value_id = $val->id;
									$item_attribute_value->save();
								}
							endforeach;
						}
					endforeach;
	
					// generate all possible combinations of attributes
					$this->_generate_inventory_items($item);
					
					$this->request->redirect('admin/merchmanagement/items/index/'.$category_id);
				}
				catch (ORM_Validation_Exception $e) {
					$errors = $e->errors('models');	
			}
		}
		$this->template->content = $view;
	}
	
	public function action_edit() {
		$item_id = $this->request->param('id');
		$item = ORM::factory('item', $item_id);
		$category = $item->category;
		$view = View::factory('admin/merchmanagement/items/edit');
		$view->set('category', $category);
		$view->set('item', $item);
		$view->bind('errors', $errors);
		
		if($_POST) {
			$item->values($_POST);
			try {
				$item->save();
				$this->request->redirect('admin/merchmanagement/items/index/'.$category->id);
			}
			catch(ORM_Validation_Exception $e) {
				$errors = $e->errors('models');
				
			}
		}
		
		$this->template->content = $view;
	}
	
	public function action_save() {
		$error_message = NULL;
		$image_id = NULL;
		$item = ORM::factory('item');
		$item->values($_POST);
		
		if($this->request->method() == Request::POST) {
			if(isset($_FILES['image'])) {
				$image_id = $this->_save_image($_FILES['image']);
			}
		}
		
		if(! $image_id) {
			$error_message = 'There was a problem while uploading the image.
				Make sure it is uploaded and must be JPG/PNG/GIF file.';
		}
		
		$item->image_id = $image_id;
		
		$item->save();
		
		// Add the attributes values for the item.
		$attributes = $item->category->attributes->find_all();
		foreach($attributes as $attr):
			if(isset($_POST['attr'.$attr->id])) {
				$item_attribute = ORM::factory('itemAttribute');
				$item_attribute->item_id = $item->id;
				$item_attribute->attribute_id = $attr->id;
				$item_attribute->save();
				foreach($attr->values->find_all() as $val) :
					if(isset($_POST['value'.$val->id])) {
						$item_attribute_value = ORM::factory('itemAttributeValue');
						$item_attribute_value->itemattribute_id = $item_attribute->id;
						$item_attribute_value->value_id = $val->id;
						$item_attribute_value->save();
					}
				endforeach;
			}
		endforeach;
		
		$this->_generate_inventory_items($item);
			
		$this->request->redirect('admin/merchmanagement/inventory/edit/'.$item->category->id);
		
	}
	
	protected function save_attributes($item) {
		$attributes = $item->category->attributes->find_all();
		foreach($attributes as $attr):
			if(isset($_POST['attr'.$attr->id])) {
				$item_attribute = ORM::factory('itemAttribute');
				$item_attribute->item_id = $item->id;
				$item_attribute->attribute_id = $attr->id;
				$item_attribute->save();
				foreach($attr->values->find_all() as $val) :
					if(isset($_POST['value'.$val->id])) {
						$item_attribute_value = ORM::factory('itemAttributeValue');
						$item_attribute_value->itemattribute_id = $item_attribute->id;
						$item_attribute_value->value_id = $val->id;
						$item_attribute_value->save();
					}
				endforeach;
			}
		endforeach;
		
	}
	
	/**
	 *	Takes a _FILE array of an image and saves the image. 
	 * @param $image
	 */
	protected function _save_image($image) {
		if(
			! Upload::valid($image) OR
			! Upload::not_empty($image) OR
			! Upload::type($image, array('jgp', 'jpeg', 'png', 'gif')))
		{
			return FALSE;
		}
		
		$directory = DOCROOT.'images/';
		$thumb_directory = DOCROOT.'images/thumbs/';
		
		if($file = Upload::save($image, NULL, $directory)) {
			$filename = strtolower(Text::random('alnum', 20)).'.jpg';
			
			Image::factory($file)
				->resize(140,180,Image::AUTO)
				->save($directory.$filename);
			
			Image::factory($file)
				->resize(100,100,Image::AUTO)
				->save($thumb_directory.$filename);
			
			// Delete the temporary file.
			unlink($file);
			
			$thumb = ORM::factory('thumb');
			$thumb->dir = $thumb_directory;
			$thumb->filename = $filename;
			$thumb->mimetype = $image['type'];
			$thumb->save();
			
			$image_obj = ORM::factory('image');
			$image_obj->dir = $directory;
			$image_obj->filename = $filename;
			$image_obj->mimetype = $image['type'];
			$image_obj->thumb_id = $thumb->id;
			$image_obj->save();
			
			return $image_obj->id;
		}
		
		return FALSE;
	}
	
	protected function _generate_inventory_items($item) {
		$item_attrs = $item->item_attributes->find_all();
		
		if(count($item_attrs) == 0) {
			$inv_item = ORM::factory('inventoryItem');
			$inv_item->item_id = $item->id;
			$inv_item->quantity = 0;
			$inv_item->save();
			return;
		}	
		
		$input = array();
		foreach($item_attrs as $item_attr):
			$input[$item_attr->attribute->id] = array();
			$vals = ORM::factory('itemAttributeValue')
				->where('itemattribute_id', '=', $item_attr->id)
				->find_all();
			foreach($vals as $val):
				$input[$item_attr->attribute->id][] = $val->value_id;
			endforeach;
		endforeach;
		
		// build cartesian product of all attribute values so that all
		// possible combinations are added to database.
		$output = $this->cartesian($input);
		
		// use cartesian product array to add all possibly combinations
		// of attribute values to database.
		foreach($output as $combo):
			$inv_item = ORM::factory('inventoryItem');
			$inv_item->item_id = $item->id;
			$inv_item->quantity = 0;
			$inv_item->save();
			foreach($combo as $key => $value):
				$inv_item_attr = ORM::factory('inventoryItemAttribute')	;
				$inv_item_attr->inventory_item_id = $inv_item->id;
				$inv_item_attr->attribute_id = $key;
				$inv_item_attr->value_id = $value;
				$inv_item_attr->save();
			endforeach;
		endforeach;
		
	}
	
	/**
	 * Code submitted by Jon on stackoverflow
	 * stackoverflow.com/questions/6311779/finding-cartesian-product-with-php-associative-arrays
	 * 
	 * input an array like:
	 * $input = array(
	 *     attr1_id => array(possible_value1_id, possible_value2_id),
	 *     attr2_id => array(possible_value1_id, possible_value2_id),
	 *     attr3_id => array(possible_value1_id, possible_value2_id),
	 * );
	 * 
	 * output will be:
	 * array
	 * (
	 *     [0] => array
	 *         (
	 *             [attr1_id] => [possible_value_id],
	 *             [attr2_id] => [possible_value_id],
	 *             [attr3_id] => [possible_value_id],
	 *         ),
	 *     [1] => array
	 *         (
	 *             [attr1_id] => [possible_value_id],
	 *             [attr2_id] => [possible_value_id],
	 *             [attr3_id] => [possible_value_id],
	 *         ),
	 *     etc....
	 * )
	 * 
	 */	
	
	protected function cartesian($input) {
		$result = array();
		
		while (list($key, $values) = each($input)) {
			// If a sub-array is empty, it doesn't affect the cartesian product
			if (empty($values)) {
				continue;
			}
		
			// Seeding the product array with the values from the first sub-array
			if (empty($result)) {
				foreach($values as $value) {
					$result[] = array($key => $value);
				}
			}
			else {
				// Second and subsequent input sub-arrays work like this:
				//   1. In each existing array inside $product, add an item with
				//      key == $key and value == first item in input sub-array
				//   2. Then, for each remaining item in current input sub-array,
				//      add a copy of each existing array inside $product with
				//      key == $key and value == first item of input sub-array
		
				// Store all items to be added to $product here; adding them
				// inside the foreach will result in an infinite loop
				$append = array();
		
				foreach($result as &$product) {
					// Do step 1 above. array_shift is not the most efficient, but
					// it allows us to iterate over the rest of the items with a
					// simple foreach, making the code short and easy to read.
					$product[$key] = array_shift($values);
		
					// $product is by reference (that's why the key we added above
					// will appear in the end result), so make a copy of it here
					$copy = $product;
		
					// Do step 2 above.
					foreach($values as $item) {
						$copy[$key] = $item;
						$append[] = $copy;
					}
		
					// Undo the side effecst of array_shift
					array_unshift($values, $product[$key]);
				}
		
				// Out of the foreach, we can add to $results now
				$result = array_merge($result, $append);
			}
		}
		
		return $result;
	}
	
}
